#include "DManSta.h"

DManSta_T* DManSta_t;

AM_Switch MA_Switch;			//< 手自动切换允许信号

//************************************
// Method:    	CALCU_SAMA					//< SAMA运算函数
// Programmer:  duan
// Time:		2019/06/17
// Returns:   	bool						//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	float dt					//< 运算周期
// Parameter: 	bool * DI					//< 数字量输入值数组指针
// Parameter: 	bool * DO					//< 数字量输出值数组指针
// Parameter: 	bool * AI					//< 模拟量输入值数组指针
// Parameter: 	bool * AO					//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(DManSta)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
	/****************变量定义区开始**************/

	
	/*<<<<<定义输入变量>>>>>*/
	bool PV;							//< 过程变量输入
	//< AM_Switch MA_Switch;			//< 手自动切换允许信号

	/*<<<<<定义输出变量>>>>>*/
	bool Output_Value;					//< 数字量输出
	DMS_AM_Sta MA_Staout;				//< 手自动状态指示输出

	/*<<<<<定义参数变量>>>>>*/
	bool Man_Value;						//< 手动输出值
	DMS_AM_Sta MA_Sta;					//< 手自动方式选择
	DMS_Work_Mode Mode;					//< 工作方式
	float Pulse_Width;					//< 脉冲宽度

	/*<<<<<定义中间变量>>>>>*/
	int* Init_Count;					//< 初始化标志
	int* ManOut;
	float* PW_Num;						//< 记录脉冲长度
	bool* DMS_PulseFlag;
	/****************变量定义区结束**************/

	NAME(DManSta)* Obj = (NAME(DManSta)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	PV = DI[0];
	MA_Switch = (AM_Switch)DI[1];
	
	/*<<<<<参数变量赋值>>>>>*/
	Man_Value = Obj->Par.Man_Value;
	MA_Sta = Obj->Par.MA_Sta;
	Mode = Obj->Par.Mode;
	Pulse_Width = Obj->Par.Pulse_Width;

	/*<<<<<中间变量赋值>>>>>*/
	Init_Count = &(Obj->Sta.Init_Count);
	ManOut = &(Obj->Sta.ManOut);
	PW_Num = &(Obj->Sta.PW_Num);
	DMS_PulseFlag = &(Obj->Sta.DMS_PulseFlag);

	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/
	if (PV != false && PV != true)
		return false;
	if (MA_Switch != Yes_Switch && MA_Switch != NO_Switch)
		return false;

	if (Init_Count[0] == 0)									//< 模块初始化
	{
		Output_Value = Man_Value;
		ManOut[0] = Output_Value;
		Init_Count[0] += 1;
	}

	if (MA_Sta == DMS_AUTO && MA_Switch == Yes_Switch)		//< 选择手自动方式：自动&&允许手自动切换   
	{
		Output_Value = PV;
		ManOut[0] = Output_Value;
		MA_Staout = DMS_AUTO;
	}
	else													//< 手动模式
	{
		if (Mode == DMS_Pulse)								//< 实现脉冲信号，对于工作方式，在命令字中实现
		{
			if (DMS_PulseFlag[0] == true)					
			{
				if (PW_Num[0] > 0)
					ManOut[0] = 1;
				else if (PW_Num[0] < 0 || PW_Num[0] == 0)
				{
					ManOut[0] = 0;
					PW_Num[0] = 0;
					DMS_PulseFlag[0] = false;
				}
				PW_Num[0] -= dt;
			}
		}

		Output_Value = ManOut[0];
		MA_Staout = DMS_MAN;
	}

	/**************算法功能实现结束**************/
	/********************************************/
	/****************运算结果输出**************/
	DO[0] = Output_Value;
	DO[1] = MA_Staout;
	/**************运算结果输出完毕************/
	return true;
}



//************************************
// Method:    	BCPARA						//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  duan
// Time:		2019/06/17
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	void ** Data				//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(DManSta)(Model_Base_t* arg, void** Data)
{
	NAME(DManSta)* Obj = (NAME(DManSta)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA						//< 备份SAMA运算中间参数
// Programmer:  duan
// Time:		2019/06/17
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 指定模块类型链表的指针
// Parameter: 	void ** Data				//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(DManSta)(Model_Base_t* arg, void** Data)
{
	NAME(DManSta)* Obj = (NAME(DManSta)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA							//< 解析备份的SAMA运算中间参数
// Programmer:  duan
// Time:		2019/06/17
// Returns:   	int								//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(DManSta)(Model_Base_t* arg, void** Data)
{
	NAME(DManSta)* Obj = (NAME(DManSta)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR					//< 在线修改模块参数函数
// Programmer:  duan
// Time:		2019/06/17
// Returns:   	int							//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg			//< 指定模块类型链表的指针
// Parameter: 	void** Data					//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(DManSta)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(DManSta)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR					//< 初始化模块运算中间参数
// Programmer:  duan
// Time:		2019/06/17
// Parameter: 	Model_Base_t* arg			//< 模块参数结构体指针
//************************************
void INIT_STAPAR(DManSta)(Model_Base_t* arg)
{
	NAME(DManSta)* name = (NAME(DManSta)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/

	/**************对中间变量结构体的相关参数进行赋值结束************/
}



//************************************
// Method:    	CMD_DEAL					//< 与模块相关的命令字处理函数
// Programmer:  duan
// Time:		2019/06/17
// Returns:   	void					
// Parameter: 	Model_Base_t* arg			//< 指定模块类型链表的指针
// Parameter: 	void* Data					//< 信息头指针
// Parameter: 	char* CMD					//< 命令字
//************************************
void CMD_DEAL(DManSta)(Model_Base_t* arg, void* Data, const char* CMD)
{
#define	MEMREAD1(var)	MEMREAD(var, Data)

	int _iLen = 0;
	int tmp_Init;
	float tmp_ManOut;
	
	NAME(DManSta)* name = (NAME(DManSta)*)arg;

	if (!strcmp(CMD, "MDO"))						//< 数字量直接输出0/1
	{
		MEMREAD1(tmp_Init);
		if (tmp_Init == 0)							//< 输出0命令
			name->Sta.ManOut = 0;
		if (tmp_Init == 1)							//< 根据不同的工作方式，执行输出1命令
		{
			if (name->Par.Mode == DMS_Pulse)		//< 脉冲
			{
				if (name->Sta.ManOut == 0)			//< 必须满足当前为0
				{
					name->Sta.PW_Num = name->Par.Pulse_Width;
					name->Sta.DMS_PulseFlag = true;
				}
			}

			if (name->Par.Mode == DMS_Turn_Over)	//< 翻转
			{
				if (name->Sta.ManOut == 0)
					tmp_ManOut = 1;
				else
					tmp_ManOut = 0;

				name->Sta.ManOut = tmp_ManOut;
			}

			if (name->Par.Mode == DMS_Long_Signal)	//< 长信号
				name->Sta.ManOut = tmp_Init;
		}
	}
	else if (!strcmp(CMD, "MDS"))					//< 手动、自动切换
	{
		MEMREAD1(tmp_Init);
		if (MA_Switch == Yes_Switch)
			name->Par.MA_Sta = (DMS_AM_Sta)tmp_Init;
	}
	

#undef MEMREAD1
}
